#include "kernel.h"

/*Message Envelope class member function*/
MsgEnv::MsgEnv(){
    sender_pid=target_pid=num_clock_ticks=0;
    type=7;
    next=NULL;
}

/*Message Envelope Queue Member Functions*/
MsgEnvQ::MsgEnvQ(){
    head=NULL;
    tail=NULL;
    size=0;
    return;
}

MsgEnvQ::MsgEnvQ(int NumOfNodes){
    head=NULL;
    tail=NULL;
    size=0;
    if (NumOfNodes>0){
        MsgEnv *cur;
        cur=new MsgEnv;
        head=cur;
        tail=cur;
        cur->next=NULL;
        size++;
        while (size<NumOfNodes){
            cur=new MsgEnv;
            tail->next=cur;
            tail=cur;
            cur->next=NULL;
            size++; 
        }
    }
    return;
}

int MsgEnvQ::enqueue(MsgEnv * newNode){
    if(newNode==NULL){
        return 0;
    }
        
    if (size==0){
        head=newNode;
        tail=newNode;
        size++;
        return 1;
    }
    tail->next=newNode;
    tail=newNode;	  
    newNode->next=NULL;
    size++;
    //cout << "enqueue!";    
    return 1;
}

MsgEnv * MsgEnvQ::dequeue(){
    MsgEnv * temp;
    if (this->size == 0|| this->head==0){
            //cout << "its empty !";
            return NULL;
    }		
    temp=head;
    head=temp->next;
    temp->next=NULL;
    size--;
    //cout << "dequeue!";
    return temp;
}

int MsgEnvQ::getsize(){//count number of nodes in the queue
    return size;
}



/*Class PCB member functions*/
PCB::PCB(){
    pid=priority=status=0;
    msgQ=NULL;
    next=NULL;
    address=NULL;
}

/*Class PCBQ member functions*/
PCBQ::PCBQ(){
    head=NULL;
    tail=NULL;
    size=0;
}

//not tested yet
int PCBQ::enqueue(PCB * newNode){
    //printf("(in enqueue) the pcb gets enqueued is [%d] \n",newNode->pid);
    if(newNode==NULL){
        return 0;
    }
    
    PCB * check=head;
 //   printf("after declear check\n");
    for(int i=0; i<size; i++)
    {    
        if(check==newNode)
        {  
      //     printf("in the if statement and about to set check to null\n");
           check=NULL;
        //   printf("check is null, returning\n");
           return 1;
        }
       // printf("getting to next pcb\n");
        if(check->next!=NULL)
           check=check->next;
        //printf("next pcb\n");
    }
    check=NULL;    
    if (size==0){
        head=newNode;
        head->next=NULL;
        tail=newNode;
        //tail->next=NULL;
        size++;
        return 1;
    }
    else{
        tail->next=newNode;
        tail=tail->next;	  
        tail->next=NULL;
        size++;
        //cout << "enqueue!";
        //printf("size of the queue is [%d]\n",size);
        return 1;
    }
}

PCB * PCBQ::dequeue(){
	PCB * temp;
//        if(head!=NULL){
//            printf("(in dequeue) before head is [%d] \n",head->pid);
//            if(head->next!=NULL){
//                printf("(in dequeue) before head next is [%d] \n",head->next->pid);
//            }
//        }
//        if(tail!=NULL){
//            printf("(in dequeue) before tail is [%d] \n",tail->pid);             
//        }
//        
//	if (this->size == 0|| this->head==NULL){
//		//cout << "its empty !";
//		return NULL;
//	}
        temp=head;        
        head=head->next;        
	temp->next=NULL;
        if(head==NULL){
            tail=NULL;
        }
	size--;
        if(head!=NULL){
            printf("(in dequeue) after head is [%d] \n",head->pid);
            if(head->next!=NULL){
                printf("(in dequeue) after head next is [%d] \n",head->next->pid);
            }
        }
        if(tail!=NULL){
            printf("(in dequeue) after tail is [%d] \n",tail->pid);             
        }
	//cout << "dequeue!";
	return temp;
}


PCB * PCBQ::remqueue(int target_pid){
	PCB * temp,* prev;
        prev=this->head;
        temp=this->head;
        while(temp != NULL){
            if(temp->pid==target_pid){
                prev->next=temp->next;
                temp->next=NULL;
                size--;
                return temp;
            }
            else{
                prev=prev->next;
                temp=prev->next;
            }                
        }
        return NULL;
}

int PCBQ::getsize(){//count number of nodes in the queue
		return size;
}

int PCBQ::get_head_id(){//count number of nodes in the queue
    if(head==NULL){
        return 100;
    }
    else
        return head->pid;
}

int PCBQ::get_tail_id(){//count number of nodes in the queue
    if(tail==NULL){
        return 100;
    }
    else
        return tail->pid;
}
